<template>
  <div class="fixed-top bg-white bg-opacity-75" style="backdrop-filter: blur(10px)">
    <div class="d-flex flex-fill justify-content-between align-items-center ">
      <div class="d-flex align-items-center d-lg-flex">
        <n-image
            width="60"
            :src="logoUrl"/>
        <div class="d-none d-sm-block">
          <div class="display-6">NewBingVue</div>
        </div>
      </div>
      <div class="p-3 d-flex align-items-center">
        <n-input v-model:value="cookie" clearable class="m-1" type="password" placeholder="Cookie" round></n-input>
        <n-button @click="setCookie" quaternary>设置</n-button>
        <n-button @click="handleRemoveAllCookie" quaternary>清除</n-button>
        <n-button @click="handleReload" quaternary>刷新</n-button>
      </div>
    </div>

    <div class="placeholder-wave text-light text-center bg-success bg-opacity-50" v-if="isSpeaking">
      <span class="placeholder-xs col-12">{{ isSpeaking ? '正在响应' : '' }}</span>
    </div>

  </div>

  <div class="d-flex flex-column flex-fill justify-content-between  h-100">
    <div :class="getChatTypeBg()"
         class="bg-gradient  d-flex flex-fill overflow-hidden bg-opacity-25 ">
      <n-scrollbar ref="scrollbarRef" @scroll="onScroll">
        <div class="container">
          <div class="text-center p-5 mt-5">
            <h1>NewBingVue</h1>
            <h5>和NewBing聊天</h5>
          </div>
          <div class="text-center pb-5">
            <button @click="changeChatType('create')"
                    :class="[chatType==='create'?'bg-primary':'bg-white']"
                    class="btn bg-gradient rounded-pill m-1"
                    style="width: 25%;height: 80px">
              <div class="d-flex flex-column">
                <div>更多</div>
                <strong>有创造力</strong>
              </div>
            </button>
            <button @click="changeChatType('balance')"
                    :class="[chatType==='balance'?'bg-danger':'bg-white']"
                    class="btn bg-gradient rounded-pill m-1"
                    style="width: 25%;height: 80px">
              <div class="d-flex flex-column">
                <div>更多</div>
                <strong>平衡</strong>
              </div>
            </button>
            <button @click="changeChatType('accurate')"
                    :class="[chatType==='accurate'?'bg-warning':'bg-white']"
                    class="btn bg-gradient rounded-pill m-1"
                    style="width: 25%;height: 80px">
              <div class="d-flex flex-column">
                <div>更多</div>
                <strong>准确</strong>
              </div>
            </button>
          </div>
          <div id="chat">
            <div class="bing">
              <div class="adaptiveCardsFatherDIV">
                <div class="textBlock markdown-body">
                  我已经准备好啦！快和我聊天吧！
                </div>
                <div class="throttling">
                  0 / 0
                </div>
              </div>
            </div>
          </div>
        </div>
      </n-scrollbar>
    </div>
    <div class="bg-primary bg-opacity-10 position-relative">
      <div id="SearchSuggestions" class="position-absolute  bg-gradient bg-opacity-25">
      </div>
      <div class="container d-flex p-2">
        <transition name="changeShow" appear>
          <n-button v-show="!onMessageIsOKClose" class="bg-gradient rounded-4 bg-white h-auto m-1" @click="handleRestart">
            <div class="d-sm-flex">
              <div>开始</div>
              <div>新主题</div>
            </div>
          </n-button>
        </transition>

        <div class="flex-fill position-relative m-1">
          <n-input class="rounded-4 p-2 " type="textarea"
                   placeholder="请输入..."
                   v-model:value="text"
                   @keydown.enter.prevent="handleSend"
                   :autosize="{minRows:2,maxRows:3}"></n-input>
          <div class="position-absolute" style="bottom: 5px;right: 5px">
            <n-button type="info" quaternary round @click="handleSend">
              发送
            </n-button>
          </div>
        </div>

      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
//@ts-ignore
import logoUrl from '@/assets/logo.png'
import {onMounted, ref} from "vue";
import {createChat} from "@/views/chat/js/bingChatHub";
import {getByID, porserMessages} from "@/views/chat/js/parserReturn";
import {nextStartMessage, nextStartProposes} from "@/views/chat/js/ChatMessages";
//@ts-ignore
import JsCookie from 'js-cookie'
import {useAppStore} from "@/store";
import router from "@/router";

const appStore = useAppStore()
const scrollbarRef = ref()
const text = ref('')


const cookie = ref(appStore.cookie || '_EDGE_V=1; SRCHD=AF=NOFORM; MUID=21D75C6C70086CE523A24E93714B6DB3; _EDGE_S=F=1&SID=0F5902EEDFCE6A9D31991011DE8D6BFD; SRCHUID=V=2&GUID=D28DD38AE19F4B179CBB3F4FCBEC4FDE&dmnchg=1; _UR=QS=0&TQS=0; ipv6=hit=1682488041766&t=4; ANON=A=2F6D717519E26D896ECC6D65FFFFFFFF&E=1c3d&W=1; NAP=V=1.9&E=1be3&C=W9W3uuV-yvWSoLqwR6zN1r53ItvKO7wTN0QBWfQoa85Kgz8eN52obA&W=1; PPLState=1; KievRPSSecAuth=FABSBBRaTOJILtFsMkpLVWSG6AN6C/svRwNmAAAEgAAACAd18j0njrJwEARmFkll7fVNdK+yaPekhO+OT8714pUEfzppK9a//hdznEE2cPHCfHUHh/CQ90Ja/ka7AHXFWe7QJ3Ae3+zrSNi1Au4yIO+FHUL/Sl69WD5+6hXP8fqHWW7Fcg0AJWlMN0S4r0aWG2czBI3U6iJ/2ADeg4znv9qXRlJkr+V7eiF+tA+J7gqCtP5ruTcDRQOtVwDcTeSFxTjxp1aAwSSMhrXLGrz3DA2bPQqMPv7JbzTEtljY6gM40L8iBCZXA4wCkz6pfiOtJYnOswEIvLCUMI3/jttaD2ksCI1ZY9cwY6bctNdlPR5hMMmQCrYhnbmSzbUVO+/wmLfdTpAoZWgkJoLdW7mxuIdA5V6F9qdNnwCBxsSeAj9rM7JtC6E9m9oKP9AdJEWOR4To8WCvKB7ERSxgtmer1elxRu51BI7m5PIvBMWcknkSBCXVtCeNiLv1gV9XyRPCLMqb4Be+u/kwis5PxOKeyjG8/gKddHy1fVecC5BI91yRUpiIlQTm73Q11w7jUwx51C2NtITVkAIdTs9OKzq1ISYsQNXlCPoPLI6RzEpVogNmNVg9I9a/ihpaOTpfGHNgnVBXbJ2zc++KqX/Rr3NMqE/hYwp1t8zFbd15Vg+mps9Wek+mD0j1q4VzbExJAodnhqy8X5/ZZaXz1EjA2FJoNHfdQ3Ej1/gUjoMz4YWzhN2UxpEbXKpE6qB+vHhH2GQ+GE2KaPpKQ8Ul6zQYyW5y1mUactcQUcgiVkEOTh8GD3yL8CUwVZj8n+RsmaKeSVJ5PDFdGPGuRPHoj6N4oC3SaoTD931D0ZA+877oMlkiA1P20olVrigY8zCgt0z8zRk6OAaPThaGmHCHvsZQppgo1WZsGL4S+CRC8CBKH6dpqQDyUDN+f0BrNrZD8z980UVTmSFBBrXVfk7yj4NEaczbujJRZu0sjYr/hiUpqHIPR1XBq9QXWQyd4JDhgqxzczOwTqEsg3qQKgBLmRrfgynwJGEb927wRkJDx8FFjqNJdUmH0KND8vKo+vcqc4G2nHPdK3dzDRdqZIgRcdpAQwvWO7I2dMUEuEPLbw7YkXLc7AmVxAl5Ad1i7bfVL6yNQv9NGVg/DHbrA9RIm8TGppWOl9Q2JDKH7WCVjyON8xneNlvcCaoIClHta9PZYztj+WI1+PbwT13m9LXbSXpu9TlYY+SUUA+YEjX4lrvP5LHoIJJkkm105CXqDC/5jG7RCDlZcXwsefRmlcRo9Q50K8GRaeRmZXHQjqXBofDO+Fy3u/ugSp7lGCgPZxkumav0j1NqH7oZdjzuTPIionQjVtZuYJehRgcb+NE93ctxub3OXpokvcGS2AnAJEBAR9l6a5bGsNJGGBFThjAOGa2/LFk3exjiNjyrQXrQ5YesIhQAjqLuGbcXOve/I0GMCLG0OHUIkME=; _U=1P1liW5yHPvMUSq2zpRsewd_6aSTYi4Trt6jpeDs39sy5ki-_ByWy4aV97Jc8X0xM91hGMMH7rjcPuWUCTFcLy6CK8haZpfxv9mOu1Xqr089cl39Je63Zf0V98EiDZgYuKNJITCG7j83ZcO1oBpmWXbsFmahpCfT2Hby2vOJFffcH6mfNTlt3L71tdnu')
const chatType = ref('balance')
const talk = ref()
const returnMessage = ref()
const isSpeaking = ref(false)
const onMessageIsOKClose = ref(true)
const throttling = ref({
  "maxNumUserMessagesInConversation": 0,
  "numUserMessagesInConversation": 0
})

let chat: any
let searchSuggestions: any

onMounted(() => {
  chat = document.getElementById('chat');
  searchSuggestions = document.getElementById('SearchSuggestions');
  searchSuggestions.style.opacity = 1;
  handleRestart()
  setCookie()
})
const handleReload=()=>{
  router.go(0)
}
const handleRemoveAllCookie=()=>{
  removeAllCookie()
  cookie.value=''
  window.$message.success('清除成功')
}
const removeAllCookie = () => {
  let cookies = document.cookie.split("; ");
  for (let i = 0; i < cookies.length; i++) {
    let t = cookies[i].split("=")
    JsCookie.remove(t[0])
  }
  appStore.cookie=''
}
const setCookie = () => {
  removeAllCookie()
  let tmp = cookie.value
  appStore.cookie = tmp
  let s = tmp.split(" ");
  for (let i = 0; i < s.length; i++) {
    let t = s[i].split("=")
    JsCookie.set(t[0], t[1])
  }
  window.$message.success('设置成功')
}

const changeChatType = (val: any) => {
  chatType.value = val
  handleRestart()
}
const getChatTypeBg = () => {
  if (chatType.value === 'create') {
    return 'bg-primary'
  }
  if (chatType.value === 'balance') {
    return 'bg-danger'
  }
  if (chatType.value === 'accurate') {
    return 'bg-warning'
  }
}


const handleSend = async () => {
  if (isSpeaking.value) {
    window.$message.warning('正在响应,请等待')
    return;
  }
  if (text.value === '') {
    window.$message.error('请输入内容')
    return
  }
  addMyChat(text.value)
  if (!talk.value) {
    isAsking()
    let r = await createChat(chatType.value)
    if (!r.ok) {
      addError(r.message)
      isFinish()
      return
    }
    talk.value = r.obj
  }
  isReplying()
  let r = await talk.value.sendMessage(text.value, onMessage)
  text.value = ''
  if (!r.ok) {
    addError(r.message)
    isFinish()
    return
  }
  returnMessage.value = r.obj
  isReplying()

}


const onMessage = (json: any, returnMessage: any) => {
  if (json.type == "close") {
    isFinish()
    if (!onMessageIsOKClose) {
      addError("聊天异常中断了！可能是网络问题。");
    }
    return;
  }
  if (json.type == 'error') {
    console.log(json)
    addError("连接发生错误：" + json.mess);
    return;
  }
  onMessageIsOKClose.value = false
  console.log(json)
  scrollbarRef.value.scrollBy({top: 99999999})
  if (json.type == 3) {
    returnMessage.getCatWebSocket().close(1000, 'ok');
  } else if (json.type == 1) {  //对话中
    porserArguments(json.arguments);
  } else if (json.type == 2) {  //对话完成
    porserType2Item(json.item);
  } else {  //6 断线检测
    console.log(JSON.stringify(json));
  }
}


/**
 * 解析arguments
 * 解析聊天消息，将消息添加到页面
 * **/
const porserArguments = (argumentss: any) => {
  for (let i = 0; i < argumentss.length; i++) {
    porserType2Item(argumentss[i]);
  }
}
//解析type2的item
const porserType2Item = (item: any) => {
  let chatDiv = document.getElementById('chat');
  if (item.result) {
    let result = item.result;
    if (result.value == 'Success') {
    } else if (result.value == 'Throttled') {
      addError(result.message);
      addError('24消息请求数达到了限制！');
    } else {
      addError(result.message);
      addError('发生未知错误！');
    }
  }
  if (item.throttling) {
    throttling.value = item.throttling;
  }
  if (item.messages) {
    //@ts-ignore
    let nextFather = getByID(item.requestId, 'div', chatDiv, 'bing');
    porserMessages(item.messages, nextFather, throttling.value);
    searchSuggestionsAddOnclick()
  }
}
const searchSuggestionsAddOnclick = () => {
  let adds = document.querySelectorAll("#SearchSuggestions>a");
  for (let add of adds) {
    //@ts-ignore
    add.onclick = (event: any) => {
      if (searchSuggestions.style.opacity >= 1) {
        text.value = event.target.innerHTML
        handleSend();
      }
    }
  }
}

const onScroll = (e: any) => {
  const {scrollTop, scrollHeight, clientHeight} = e.target
  if (scrollTop + clientHeight + 25 >= scrollHeight) {
    searchSuggestions.style.opacity = 1;
  } else {
    searchSuggestions.style.opacity = 0;
  }
}
const isAsking = () => {
  isSpeaking.value = true
}
const isReplying = () => {
  isSpeaking.value = true
}
const isFinish = () => {
  isSpeaking.value = false
}
const addMyChat = (message: any) => {
  let bobo = document.createElement('div');
  bobo.style.whiteSpace = 'pre-wrap';
  bobo.innerText = message;
  bobo.classList.add('bobo');
  bobo.classList.add('markdown-body');
  let go = document.createElement('div');
  go.classList.add('my');
  go.appendChild(bobo);
  chat.appendChild(go);
  scrollbarRef.value.scrollBy({top: 99999999})
}

const addError = (message: any) => {
  let go = document.createElement('div');
  go.classList.add('error');
  go.classList.add('mb-5');
  go.innerHTML = message;
  chat.appendChild(go);
  scrollbarRef.value.scrollBy({top: 99999999})
}


const handleRestart = () => {
  onMessageIsOKClose.value = true;
  if (returnMessage.value) {
    returnMessage.value.getCatWebSocket().close(1000, 'ok');
    returnMessage.value = undefined;
  }
  talk.value = undefined;
  isFinish()
  reSetStartChatMessage()
}

/**重置聊天框和聊天建议到初始状态 */
function reSetStartChatMessage() {
  chat.innerHTML = `
		<div class="bing">
			<div class="adaptiveCardsFatherDIV">
				<div class="textBlock markdown-body">
					${nextStartMessage()}
				</div>
				<div class="throttling">
					0 / 0
				</div>
			</div>
		</div>
		`;
  searchSuggestions.innerHTML = '';
  nextStartProposes().then((prs) => {
    prs.forEach((s: any) => {
      let a = document.createElement('a');
      a.innerHTML = s;
      a.onclick = (even: any) => {
        if (searchSuggestions.style.opacity >= 1) {
          //@ts-ignore
          text.value = even.target.innerHTML
          handleSend();
        }
      }
      //@ts-ignore
      searchSuggestions.appendChild(a);
    });
  });
}

</script>

<style>
@import "css/bing.css";
.changeShow-enter-active {
  animation: changeShow 0.8s;
}
.changeShow-leave-active {
  animation: changeShow 0.8s reverse;
}
@keyframes changeShow {
  from {
    transform: translateX(-100%);
  }
  to {
    transform: translateX(0px);
  }
}
</style>